﻿using com.cyou.media.nativedownload;
using GameFramework.Resource;
using System;
using System.Collections.Generic;
using System.IO;

namespace GameFramework.Download
{
    /// <summary>
    /// Project-S 下载管理器。
    /// </summary>
    internal sealed class PSDownloadManager : GameFrameworkModule, IPSDownloadManager
    {
        private bool m_Started;
        private bool m_Paused;
        private readonly Dictionary<int, object> m_UserDataDict;

        private EventHandler<DownloadStartEventArgs> m_DownloadStartEventHandler;
        private EventHandler<DownloadUpdateEventArgs> m_DownloadUpdateEventHandler;
        private EventHandler<DownloadSuccessEventArgs> m_DownloadSuccessEventHandler;
        private EventHandler<DownloadFailureEventArgs> m_DownloadFailureEventHandler;

        private long _lastBytesForSuccess = 0;

        public PSDownloadManager()
        {
            m_Started = false;
            m_Paused = false;
            m_UserDataDict = new Dictionary<int, object>();

            m_DownloadStartEventHandler = null;
            m_DownloadUpdateEventHandler = null;
            m_DownloadSuccessEventHandler = null;
            m_DownloadFailureEventHandler = null;
#if DEVELOPMENT_BUILD || UNITY_EDITOR
            TakeDownloadManager.Instance.ShowLog(true);
#else
		    TakeDownloadManager.Instance.ShowLog(false);
#endif
            TakeDownloadManager.Instance.KeepAliveType_Ios(1);
            TakeDownloadManager.Instance.InitSdk(5,10,"新天龙八部",true);//第二个参数超时连接
            TakeDownloadManager.Instance.SetDownloadStartEvent(OnDownloadStart);
            TakeDownloadManager.Instance.SetDownloadUpdateEvent(OnDownloadUpdate);
            TakeDownloadManager.Instance.SetDownloadSuccessEvent(OnDownloadSuccess);
            TakeDownloadManager.Instance.SetDownloadFailureEvent(OnDownloadFailure);
            TakeDownloadManager.Instance.SetAllDownloadCompleteEvent(OnAllDownloadComplete);
            //TakeDownloadManager.Instance.SetHasPermissionEvent(OnHasPermission);

            GameFrameworkLog.Warning("CYOU download ready.");
        }

        /// <summary>
        /// 获取游戏框架模块优先级。
        /// </summary>
        /// <remarks>优先级较高的模块会优先轮询，并且关闭操作会后进行。</remarks>
        internal override int Priority
        {
            get
            {
                return 5;
            }
        }

        /// <summary>
        /// 获取或设置下载是否被暂停。
        /// </summary>
        public bool Paused
        {
            get
            {
                return m_Paused;
            }
            set
            {
                UnityEngine.Debug.LogWarning("控制下载暂停:" + value);
                m_Paused = value;
                if (m_Paused)
                {
                    TakeDownloadManager.Instance.PauseDownload();
                }
                else
                {
                    TakeDownloadManager.Instance.ResumeDownload();
                }
            }
        }

        /// <summary>
        /// 获取下载代理总数量。
        /// </summary>
        public int TotalAgentCount
        {
            get
            {
                return -1;
            }
        }

        /// <summary>
        /// 获取可用下载代理数量。
        /// </summary>
        public int FreeAgentCount
        {
            get
            {
                return -1;
            }
        }

        /// <summary>
        /// 获取工作中下载代理数量。
        /// </summary>
        public int WorkingAgentCount
        {
            get
            {
                return -1;
            }
        }

        /// <summary>
        /// 获取等待下载任务数量。
        /// </summary>
        public int WaitingTaskCount
        {
            get
            {
                return -1;
            }
        }

        /// <summary>
        /// 获取或设置将缓冲区写入磁盘的临界大小。
        /// </summary>
        public int FlushSize
        {
            get
            {
                return -1;
            }
            set
            {
            }
        }

        /// <summary>
        /// 获取或设置下载超时时长，以秒为单位。
        /// </summary>
        public float Timeout
        {
            get
            {
                return -1f;
            }
            set
            {
            }
        }

        /// <summary>
        /// 获取当前下载速度。
        /// </summary>
        public float CurrentSpeed
        {
            get
            {
                return TakeDownloadManager.Instance.GetDownloadSpeed();
            }
        }

        /// <summary>
        /// 获取已下载大小
        /// </summary>
        public long CurrentByte
        {
            get {
                return TakeDownloadManager.Instance.GetDownloadBytes();
            }
        }


        public long LastBytesForSuccess
        {
            get {
                return _lastBytesForSuccess;
            }

            set
            {
                _lastBytesForSuccess = value;
            }
        }
        public long GetLengthByUrl(string url)
        {
            return TakeDownloadManager.Instance.GetDownloadBytes(url);
        }
        
        /// <summary>
        /// 下载开始事件。
        /// </summary>
        public event EventHandler<DownloadStartEventArgs> DownloadStart
        {
            add
            {
                m_DownloadStartEventHandler += value;
            }
            remove
            {
                m_DownloadStartEventHandler -= value;
            }
        }

        /// <summary>
        /// 下载更新事件。
        /// </summary>
        public event EventHandler<DownloadUpdateEventArgs> DownloadUpdate
        {
            add
            {
                m_DownloadUpdateEventHandler += value;
            }
            remove
            {
                m_DownloadUpdateEventHandler -= value;
            }
        }

        /// <summary>
        /// 下载成功事件。
        /// </summary>
        public event EventHandler<DownloadSuccessEventArgs> DownloadSuccess
        {
            add
            {
                m_DownloadSuccessEventHandler += value;
            }
            remove
            {
                m_DownloadSuccessEventHandler -= value;
            }
        }

        /// <summary>
        /// 下载失败事件。
        /// </summary>
        public event EventHandler<DownloadFailureEventArgs> DownloadFailure
        {
            add
            {
                m_DownloadFailureEventHandler += value;
            }
            remove
            {
                m_DownloadFailureEventHandler -= value;
            }
        }

        /// <summary>
        /// 下载管理器轮询。
        /// </summary>
        /// <param name="elapseSeconds">逻辑流逝时间，以秒为单位。</param>
        /// <param name="realElapseSeconds">真实流逝时间，以秒为单位。</param>
        internal override void Update(float elapseSeconds, float realElapseSeconds)
        {
        }

        /// <summary>
        /// 关闭并清理下载管理器。
        /// </summary>
        internal override void Shutdown()
        {
            m_UserDataDict.Clear();
        }

        /// <summary>
        /// 增加下载代理辅助器。
        /// </summary>
        /// <param name="downloadAgentHelper">要增加的下载代理辅助器。</param>
        public void AddDownloadAgentHelper(IDownloadAgentHelper downloadAgentHelper)
        {
        }

        public void RemoveAllDownloadAgentHelper()
        {

        }
        /// <summary>
        /// 根据下载任务的序列编号获取下载任务的信息。
        /// </summary>
        /// <param name="serialId">要获取信息的下载任务的序列编号。</param>
        /// <returns>下载任务的信息。</returns>
        public TaskInfo GetDownloadInfo(int serialId)
        {
            return default(TaskInfo);
        }

        /// <summary>
        /// 根据下载任务的标签获取下载任务的信息。
        /// </summary>
        /// <param name="tag">要获取信息的下载任务的标签。</param>
        /// <returns>下载任务的信息。</returns>
        public TaskInfo[] GetDownloadInfos(string tag)
        {
            return new TaskInfo[] { };
        }

        /// <summary>
        /// 根据下载任务的标签获取下载任务的信息。
        /// </summary>
        /// <param name="tag">要获取信息的下载任务的标签。</param>
        /// <param name="results">下载任务的信息。</param>
        public void GetDownloadInfos(string tag, List<TaskInfo> results)
        {
            results.Clear();
        }

        /// <summary>
        /// 获取所有下载任务的信息。
        /// </summary>
        /// <returns>所有下载任务的信息。</returns>
        public TaskInfo[] GetAllDownloadInfos()
        {
            return new TaskInfo[] { };
        }

        /// <summary>
        /// 获取所有下载任务的信息。
        /// </summary>
        /// <param name="results">所有下载任务的信息。</param>
        public void GetAllDownloadInfos(List<TaskInfo> results)
        {
            results.Clear();
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri)
        {
            return AddDownload(downloadPath, downloadUri, "tag", Constant.DefaultPriority, null);
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <param name="tag">下载任务的标签。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri, string tag)
        {
            return AddDownload(downloadPath, downloadUri, tag, Constant.DefaultPriority, null);
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <param name="priority">下载任务的优先级。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri, int priority)
        {
            return AddDownload(downloadPath, downloadUri, "tag", priority, null);
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <param name="userData">用户自定义数据。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri, object userData)
        {
            return AddDownload(downloadPath, downloadUri, "tag", Constant.DefaultPriority, userData);
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <param name="tag">下载任务的标签。</param>
        /// <param name="priority">下载任务的优先级。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri, string tag, int priority)
        {
            return AddDownload(downloadPath, downloadUri, tag, priority, null);
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <param name="tag">下载任务的标签。</param>
        /// <param name="userData">用户自定义数据。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri, string tag, object userData)
        {
            return AddDownload(downloadPath, downloadUri, tag, Constant.DefaultPriority, userData);
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <param name="priority">下载任务的优先级。</param>
        /// <param name="userData">用户自定义数据。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri, int priority, object userData)
        {
            return AddDownload(downloadPath, downloadUri, "tag", priority, userData);
        }

        /// <summary>
        /// 增加下载任务。
        /// </summary>
        /// <param name="downloadPath">下载后存放路径。</param>
        /// <param name="downloadUri">原始下载地址。</param>
        /// <param name="tag">下载任务的标签。</param>
        /// <param name="priority">下载任务的优先级。</param>
        /// <param name="userData">用户自定义数据。</param>
        /// <returns>新增下载任务的序列编号。</returns>
        public int AddDownload(string downloadPath, string downloadUri, string tag, int priority, object userData)
        {
            GameFrameworkLog.Warning("psdownload:AddDownload:"+ downloadPath);
            if (string.IsNullOrEmpty(downloadPath))
            {
                throw new GameFrameworkException("Download path is invalid.");
            }

            if (string.IsNullOrEmpty(downloadUri))
            {
                throw new GameFrameworkException("Download uri is invalid.");
            }
            //int lenth = (int)(userData.GetType().GetField("m_CompressedLength", System.Reflection.BindingFlags.NonPublic).GetValue(userData));
            uint length = 0;
            if (userData != null)
            {
                length = ResourceManager.GetCompressedLength(userData);
            }
            int serialId = TakeDownloadManager.Instance.AddDownload(downloadUri, downloadPath, length, "tag", priority);
            m_UserDataDict.Add(serialId, userData);
            StartDownload();
            //GameFrameworkLog.Error("[TEST LOG]AddDownload SerialId='{0}' URL='{1}' Path='{2}' Tag='{3}' Priority='{4}' UserData='{5}'", serialId, downloadUri, downloadPath, tag, priority, userData);
            return serialId;
        }
        /// <summary>
        /// 根据下载任务的序列编号移除下载任务。
        /// </summary>
        /// <param name="serialId">要移除下载任务的序列编号。</param>
        /// <returns>是否移除下载任务成功。</returns>
        public bool RemoveDownload(int serialId)
        {
            return TakeDownloadManager.Instance.RemoveDownload(serialId);
        }

        /// <summary>
        /// 根据下载任务的标签移除下载任务。
        /// </summary>
        /// <param name="tag">要移除下载任务的标签。</param>
        /// <returns>移除下载任务的数量。</returns>
        public int RemoveDownloads(string tag)
        {
            return TakeDownloadManager.Instance.RemoveDownloads(tag);
        }

        /// <summary>
        /// 移除所有下载任务。
        /// </summary>
        /// <returns>移除下载任务的数量。</returns>
        public int RemoveAllDownloads()
        {

            UnityEngine.Debug.LogWarning("移除所有下载任务");
            return TakeDownloadManager.Instance.RemoveAllDownloads();
        }
        /// <summary>
        /// 停止下载器
        /// </summary>
        public void StopDownload()
        {
            if (TakeDownloadManager.Instance)
            {
                UnityEngine.Debug.LogWarning("控制下载Stop");
                m_Started = false;
                TakeDownloadManager.Instance.StopDownload();
            }
        }

        public void StartDownload()
        {
            if (TakeDownloadManager.Instance)
            {
                UnityEngine.Debug.LogWarning("StartDownload");
                if (!m_Started)
                {
                    UnityEngine.Debug.LogWarning("控制下载start");
                    m_Started = true;
                    TakeDownloadManager.Instance.StartDownload();
                }
                
            }
        }
        public int GetDownloadPercent()
        {
            return TakeDownloadManager.Instance.GetDownloadPercent();
        }

        public bool IsBackDownloadFinished()
        {
            return TakeDownloadManager.Instance.IsDownloadFinished();
        }
        private object GetUserData(int serialId)
        {
            object value = null;
            if (m_UserDataDict.TryGetValue(serialId, out value))
            {
                return value;
            }

            return null;
        }

        private void OnDownloadStart(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return;
            }

            //GameFrameworkLog.Error("[TEST LOG]OnDownloadStart: {0}", value);

            if (m_DownloadStartEventHandler != null)
            {
                DownloadStartEventArgs eventArgs = Utility.Json.ToObject<DownloadStartEventArgs>(value);
                DownloadStartEventArgs downloadStartEventArgs = DownloadStartEventArgs.Create(eventArgs.SerialId, Path.Combine(eventArgs.DownloadPath, Path.GetFileName(eventArgs.DownloadUri)), eventArgs.DownloadUri, eventArgs.CurrentLength, GetUserData(eventArgs.SerialId));
                m_DownloadStartEventHandler(this, downloadStartEventArgs);
                ReferencePool.Release(downloadStartEventArgs);
            }
        }

        private void OnDownloadUpdate(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return;
            }

            //GameFrameworkLog.Error("[TEST LOG]OnDownloadUpdate: {0}", value);

            if (m_DownloadUpdateEventHandler != null)
            {
                DownloadUpdateEventArgs eventArgs = Utility.Json.ToObject<DownloadUpdateEventArgs>(value);
                DownloadUpdateEventArgs downloadUpdateEventArgs = DownloadUpdateEventArgs.Create(eventArgs.SerialId, Path.Combine(eventArgs.DownloadPath, Path.GetFileName(eventArgs.DownloadUri)), eventArgs.DownloadUri, eventArgs.CurrentLength, GetUserData(eventArgs.SerialId));
                m_DownloadUpdateEventHandler(this, downloadUpdateEventArgs);
                ReferencePool.Release(downloadUpdateEventArgs);
            }
        }

        private void OnDownloadSuccess(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return;
            }

            //GameFrameworkLog.Error("[TEST LOG]OnDownloadSuccess: {0}", value);
            if (m_DownloadSuccessEventHandler != null)
            {
                DownloadSuccessEventArgs eventArgs = Utility.Json.ToObject<DownloadSuccessEventArgs>(value);
                DownloadSuccessEventArgs downloadSuccessEventArgs = DownloadSuccessEventArgs.Create(eventArgs.SerialId, eventArgs.DownloadPath, eventArgs.DownloadUri, eventArgs.CurrentLength, GetUserData(eventArgs.SerialId));
                m_DownloadSuccessEventHandler(this, downloadSuccessEventArgs);
                //GameFrameworkLog.Error("[TEST LOG]DownloadSuccessEventArgs: SerialId={0} DownloadPath={1} DownloadUri={2} CurrentLength={3} UserData={4}", downloadSuccessEventArgs.SerialId, downloadSuccessEventArgs.DownloadPath, downloadSuccessEventArgs.DownloadUri, downloadSuccessEventArgs.CurrentLength, downloadSuccessEventArgs.UserData);
                ReferencePool.Release(downloadSuccessEventArgs);
                m_UserDataDict.Remove(eventArgs.SerialId);
            }
        }

        private void OnDownloadFailure(string value)
        {
            GameFrameworkLog.Warning("ps下载失败" + value);
            if (string.IsNullOrEmpty(value))
            {
                return;
            }

            //GameFrameworkLog.Error("[TEST LOG]OnDownloadFailure: {0}", value);
            if (m_DownloadFailureEventHandler != null)
            {
                DownloadFailureEventArgs eventArgs = Utility.Json.ToObject<DownloadFailureEventArgs>(value);
                DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(eventArgs.SerialId, eventArgs.DownloadPath, eventArgs.DownloadUri, eventArgs.ErrorMessage, GetUserData(eventArgs.SerialId));
                m_DownloadFailureEventHandler(this, downloadFailureEventArgs);
                ReferencePool.Release(downloadFailureEventArgs);
                m_UserDataDict.Remove(eventArgs.SerialId);
            }
        }

        private void OnAllDownloadComplete(string value)
        {
            m_Started = false;
            GameFrameworkLog.Warning("后台下载 OnAllDownloadComplete:"+value);
          /*  if (string.IsNullOrEmpty(value))
            {
                return;
            }
            Dictionary<string, long> dict = Utility.Json.ToObject<Dictionary<string, long>>(value);
            if (dict != null && dict.ContainsKey("DownloadBytesForSuccessUrl"))
            {
                long _tempBytesForSuccess = dict["DownloadBytesForSuccessUrl"];
                _lastBytesForSuccess += _tempBytesForSuccess;


            }*/
        }

        private void OnHasPermission(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return;
            }

            //GameFrameworkLog.Error("[TEST LOG]OnHasPermission: {0}", value);
        }

        public void ApplicationPause(bool isPause)
        {

        }


    }
}
